#include "sec_cmp.h"


SecCmp::CloudA::CloudA(const PrivateKey& pri): m_dec(pri), m_mulA(pri){
	// ...
}

void SecCmp::CloudA::set_nvlen(long nlens, long vlens){
	m_nlens = nlens -1;
	m_vlens = vlens;
}

void SecCmp::CloudA::dec_sub(const NTL::ZZ& sub, NTL::ZZ& beta){
	NTL::ZZ dt, pbeta;
	m_dec.Decrypt(sub, dt);
	
	if(dt > (m_dec.GetN() / 2)){
		pbeta = 0;
	}
	else{
		pbeta = 1;
	}
	
	m_dec.Encrypt(pbeta, beta);
}


void SecCmp::CloudA::dec_reenc(const NTL::ZZ& nca, const NTL::ZZ& ncb, NTL::ZZ& cmul){
	m_mulA.dec_reenc(nca, ncb, cmul);
}

SecCmp::CloudB::CloudB(const PublicKey& pub): m_enc(pub), m_mulB(pub){
	// ...
}

void SecCmp::CloudB::set_nvlen(long nlens, long vlens){
	m_nlens = nlens -1;
	m_vlens = vlens;
}

void SecCmp::CloudB::calc_sub(const NTL::ZZ& cx, const NTL::ZZ& cy, NTL::ZZ& sub){
	NTL::ZZ r0, r1;
	
	r0 = NTL::RandomLen_ZZ(m_nlens / 2 - m_vlens - 1);
	r1 = NTL::RandomLen_ZZ(m_nlens / 2 - m_vlens);
	
	NTL::ZZ xx, yy;
	
	m_enc.HE_Mul_Const(cx, NTL::ZZ(2), xx);
	m_enc.HE_Add_Const(xx, NTL::ZZ(1), xx);
	
	m_enc.HE_Mul_Const(cy, NTL::ZZ(2), yy);
	
	NTL::ZZ t, d;

	m_alpha =  NTL::RandomLen_ZZ(8) % 2;
	if (m_alpha == 1){
		m_enc.HE_Mul_Const(xx, m_enc.GetN() -1 , t);
		m_enc.HE_Add_Cipher(t, yy, d);
	}
	else{
		m_enc.HE_Mul_Const(yy, m_enc.GetN() -1 , t);
		m_enc.HE_Add_Cipher(t, xx, d);
	}
	
	m_enc.HE_Mul_Const(d, r0 , d);
	m_enc.HE_Add_Const(d, r1, sub);
}

void SecCmp::CloudB::rerandom_for_mul(const NTL::ZZ& cbeta, NTL::ZZ& nca, NTL::ZZ& ncb){
	NTL::ZZ e;
	m_enc.HE_Add_Const(cbeta, m_enc.GetN() - m_alpha, e);
	
	m_mulB.gen_two_ciphers(e, e, nca, ncb);
}

void SecCmp::CloudB::gen_res(const NTL::ZZ& cmul, NTL::ZZ& cab){
	m_mulB.gen_mul(cmul, cab);
}
